package middlewares

import (
	"encoding/base64"
	"encoding/json"
	"net/http"
	"regexp"
	"strings"
	"sync"

	"gitee.com/lflxp/dogo"
	"gitee.com/lflxp/dogo/model/admin"

	"github.com/gin-gonic/gin"
	log "github.com/go-eden/slf4go"
)

// func init() {
// 	dogo.NewRails().Use(TokenFilter())
// }
var (
	whiteRouter []string = []string{
		`^/$`,
		`^/swagger/*`,
		`^/login`,
		`^/adminfs/*`,
		`^/favicon.ico`,
		`^/auth/login`,
		`^/v3/*`,
		`^/metrics`,
		`^/cloud/xterm`,
		`^/cloud/log`,
	}
	onceWhite sync.Once
)

// func init() {
// 	dogo.NewRails().Use(TokenFilter())
// }

func AddWhiteRouter(data ...string) {
	whiteRouter = append(whiteRouter, data...)
}

func JwtTokenFilter() gin.HandlerFunc {
	return func(c *gin.Context) {
		if !isWhilteUrl(c) {
			token, err := NewGinJwtMiddlewares(AllUserAuthorizator).ParseToken(c)
			if err != nil {
				c.JSONP(401, gin.H{
					"error": err.Error(),
					"code":  "token is invaild",
				})
				return
			}

			info, err := json.Marshal(token)
			if err != nil {
				c.JSONP(401, gin.H{
					"error": err.Error(),
					"code":  "json.Marshal error",
				})
				return
			}

			var user admin.User
			err = json.Unmarshal(info, &user)
			if err != nil {
				c.JSONP(401, gin.H{
					"error": err.Error(),
					"code":  "json.Unmarshal error",
					"info":  string(info),
				})
				return
			}

			c.Request.Header.Set("username", user.Username)
			c.Request.Header.Set("token", user.Token)
			c.Next()
		} else {
			c.Next()
		}
	}
}

func TokenFilter() gin.HandlerFunc {
	return func(c *gin.Context) {
		// token := jwt.ExtractClaims(c)
		// log.Debug("ExtractClaims token ", token)

		if !isWhilteUrl(c) {
			cookie, err := c.Cookie("token")
			if err != nil {
				dogo.Errorf("未检测出token %s", err.Error())
				c.Redirect(http.StatusFound, "/login?url="+c.Request.RequestURI)
				return
			}

			// log.Debug("cookie is ", cookie)
			if cookie == "" {
				c.Redirect(http.StatusFound, "/login?url="+c.Request.RequestURI)
				return
			}

			var msg map[string]interface{}

			rs, err := base64.RawURLEncoding.DecodeString(strings.Split(cookie, ".")[1])
			if err != nil {
				dogo.Debugf("base64解码失败 %s", err.Error())
				c.Redirect(http.StatusFound, "/login?url="+c.Request.RequestURI)
				return
			}

			// log.Debugf("mid is %s", string(rs))

			err = json.Unmarshal(rs, &msg)
			if err != nil {
				dogo.Debugf("数据格式解析错误 %s", err.Error())
				c.Redirect(http.StatusFound, "/login?url="+c.Request.RequestURI)
				return
			}

			if token, ok := msg["token"]; !ok {
				dogo.Debug("未找到token字段 token invaild")
				c.Redirect(http.StatusFound, "/login?url="+c.Request.RequestURI)
				return
			} else {
				// log.Debugf("token is %v", msg)
				c.Request.Header.Set("token", token.(string))
				c.Request.Header.Set("username", msg["username"].(string))
				c.Next()
			}
		} else {
			c.Next()
		}
	}
}

func isWhilteUrl(c *gin.Context) bool {
	var rs bool

	for _, x := range whiteRouter {
		rs, _ = regexp.MatchString(x, c.Request.URL.Path)
		if rs {
			break
		}
	}

	log.Debugf("method [%s] isWhite %v path %s Url.Path %s ", c.Request.Method, rs, c.Request.RequestURI, c.Request.URL.Path)
	return rs
}
